<?php
/**
 * Author: ChenGuangHui
 * Email：13035809409@163.com
 * Date Time: 2021/7/19 10:31
 */


namespace App\Logic\Common;


use App\Enums\HttpCode;
use App\Logic\CommLogic;
use App\Models\Rbac\RbacAction;
use App\Models\Rbac\RbacMenu;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\QueryException;
use Illuminate\Support\Arr;

class MenuLogic extends CommLogic
{

    /**
     * @param $params
     * @return RbacMenu[]|array|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public function tree($params)
    {
        $menus = RbacMenu::query()
            ->where('id', '<>', 1)
            ->when(isset($params['status']), function (Builder $query) use ($params) {
                $query->where('status', $params['status']);
            })
            ->when(isset($params['is_dir']), function (Builder $query) use ($params) {
                $query->where('is_dir', $params['is_dir']);
            })
            ->when(!empty($params['name']), function (Builder $query) use ($params) {
                $query->where('name', 'like', '%' . $params['name'] . '%');
            })
            ->get()->toArray();
        if (!empty($menus)) {
            $menus = $this->_getTree($menus, 0);
        }
        return $menus ?? [];
    }

    /**
     * @param $menus
     * @param $parentId
     * @param $action
     * @return array
     */
    public function _getTree($menus, $parentId)
    {
        $tree = [];
        foreach ($menus as $m) {
            if ($m['parent_id'] == $parentId) {
                $data = $this->_getTree($menus, $m['id']);
                if (!empty($data)) {
                    $m['children'] = $data;
                }
                $tree[] = $m;
            }
        }
        return $tree;
    }

    /**
     * @param array $where
     * @param array $pageData
     * @param array $sortData
     * @return mixed
     */
    public function index($where = [], $pageData = ['pageSize' => 20, 'pageNow' => 1], $sortData = [])
    {
        $query = RbacMenu::query()
            ->where('id', '<>', 1)
            ->when(isset($where['status']), function (Builder $query) use ($where) {
                $query->where('status', $where['status']);
            })
            ->when(!empty($where['name']), function (Builder $query) use ($where) {
                $query->where('name', 'like', '%' . $where['name'] . '%');
            });

        if (!empty($sortData)) {
            $query = $query->orderBy($sortData['sortRow'], $sortData['sortType']);
        }else{
            $query = $query->orderBy('id', 'desc');
        }

        $data = $query->paginate($pageData['pageSize'], ['*'], 'page', $pageData['pageNow'])
            ->toArray();
        return $data;
    }

    /**
     * @param $data
     * @param $id
     * @param $name
     * @return mixed
     */
    public function getParent($data, $id, $name)
    {
        if (isset($data[$id])) {
            $name = $this->getParent($data, $data[$id]['parent_id'], $data[$id]['title'] . '/' . $name);
        }
        return $name;
    }

    public function getParentIds($data, $id, $arrs)
    {
        if (isset($data[$id])) {
            $arrs = $this->getParentIds($data, $data[$id]['parent_id'], Arr::prepend($arrs, $data[$id]['id']));
        }
        return $arrs;
    }

    /**
     * @param $params
     * @return bool
     * @throws \Throwable
     */
    public function store($params)
    {
        $lockName = 'menu_store_' . auth('api')->id();
        $lock = \Cache::lock($lockName, 5);
        abort_if(!$lock->get(), HttpCode::TOO_MANY_REQUESTS, '请勿重复操作！');
        \DB::beginTransaction();
        try {
            $data = array(
                'title' => $params['title'],
                'name' => $params['name'],
                'icon' => $params['icon'],
                'sort' => $params['sort'] ?? 0,
                'is_dir' => $params['is_dir'] ?? 0,
                'component' => $params['is_dir'] == 1 ? 'layout/routerView/parent' : $params['name'] .'/index',
                'status' => $params['status'],
                'auth_code' => $params['auth_code'] ?? '',
                'path' => $params['path'],
                'parent_id' => is_array($params['parent_ids']) ? Arr::last($params['parent_ids']) : 0,
                'description' => $params['description'] ?? '',
            );
            RbacMenu::query()->create($data);
            \DB::commit();
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new \Exception($exception->getMessage(), $exception->getCode());
        }
        return true;
    }

    /**
     * @param $id
     * @return RbacMenu|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     */
    public function show($id)
    {
        $data = RbacMenu::query()->where('id', $id)->first();
        abort_if(empty($data), HttpCode::FORBIDDEN, '配置不存在！');
        $menu = RbacMenu::query()->get()->keyBy('id')->toArray();
        $data->parent_ids = $this->getParentIds($menu, $data->parent_id, []);
        return $data;
    }

    /**
     * @param $params
     * @param $id
     * @return bool
     * @throws \Throwable
     */
    public function update($params, $id)
    {
        $lockName = 'menu_update_' . auth('api')->id();
        $lock = \Cache::lock($lockName, 5);
        abort_if(!$lock->get(), HttpCode::TOO_MANY_REQUESTS, '请勿重复操作！');
        $menu = RbacMenu::query()->where('id', $id)->first();
        abort_if(empty($menu), HttpCode::FORBIDDEN, '配置不存在！');
        \DB::beginTransaction();
        try {
            $data = array(
                'title' => $params['title'],
                'name' => $params['name'],
                'icon' => $params['icon'],
                'sort' => $params['sort'] ?? 0,
                'is_dir' => $params['is_dir'] ?? 0,
                'component' => $params['is_dir'] == 1 ? 'layout/routerView/parent' : $params['name'] .'/index',
                'status' => $params['status'],
                'auth_code' => $params['auth_code'],
                'path' => $params['path'],
                'parent_id' => is_array($params['parent_ids']) ? Arr::last($params['parent_ids']) : 0,
                'description' => $params['description'] ?? '',
            );
            $menu->update($data);
            \DB::commit();
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new \Exception($exception->getMessage(), $exception->getCode());
        }
        return true;
    }

    /**
     * @param $id
     * @return bool
     * @throws \Throwable
     */
    public function destroy($id)
    {
        $data = RbacMenu::query()->where('id', $id)->first();
        abort_if(empty($data), HttpCode::FORBIDDEN, '配置不存在！');
        \DB::beginTransaction();
        try {
            $data->delete();
            \DB::commit();
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new \Exception($exception->getMessage(), $exception->getCode());
        }
        return true;
    }
}
